package com.example;

import com.example.adapter.idea.Adapter;
import com.example.adapter.idea.Target;
import com.example.builder.exp1.ServiceProvider;
import com.example.builder.exp2.Circle;
import com.example.composition.InstrumentedSet;
import com.example.decorator.AutoCompleteEditText;
import com.example.decorator.Component;
import com.example.decorator.EditText;
import com.example.decorator.MultiLineEditText;
import com.example.dependency_injection.CustomFileReader;
import com.example.iterator.CustomArray;
import com.example.iterator.Iterator;
import com.example.singleton.Cat;
import com.example.singleton.Dog;
import com.example.template.PrintCalculator;
import com.example.try_with_resources.CustomAutoClosable;

import java.io.*;
import java.util.Arrays;
import java.util.HashSet;

public class Test {
    public static void main(String[] args) {
        //testBuilder();
        //testSingleton();
        //testDependencyInjection();
        //testTryWithResources();
        //testComposition();
        //testDecorator();
        //testAdapter();
        //testTemplate();
        testIterator();
    }

    public static void testIterator() {
        CustomArray<Integer> array = new CustomArray<>();
        int[] arr = new int[] {
                1,4,3,2
        };
        for (int i : arr) {
            array.add(i);
        }
        Iterator<Integer> it = array.iterator();
        while (it.hasNext()) {
            Integer next = it.next();
            System.out.println(next);
            it.remove();
        }
        System.out.println("size = " + array.size());
    }

    public static void testTemplate() {
        PrintCalculator calculator = new PrintCalculator();
        calculator.calculate();
    }

    public static void testAdapter() {
        Target target = new Adapter();
        target.targetRequest();
    }

    public static void testDecorator() {
        Component component = new EditText();
        AutoCompleteEditText autoCompleteEditText = new AutoCompleteEditText(component);
        MultiLineEditText multiLineEditText = new MultiLineEditText(component);
        autoCompleteEditText.showName();
        multiLineEditText.showName();
    }

    public static void testComposition() {
        InstrumentedSet<Integer> instrumentedSet = new InstrumentedSet<>(new HashSet<>());
        System.out.println("after init, addCount = " + instrumentedSet.getAddCount());
        instrumentedSet.add(3);
        instrumentedSet.addAll(Arrays.asList(3, 4));
        System.out.println("after add, addCount = " + instrumentedSet.getAddCount());
    }

    public static void testTryWithResources() {
        //testTryFinally();
        testTryResources();
    }

    private static void testTryResources() {
        try (CustomAutoClosable closable = new CustomAutoClosable("")) {
            closable.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void testTryFinally() {
        CustomAutoClosable closable = null;
        try {
            closable = new CustomAutoClosable("");
            closable.open();
        }finally {
            closable.doClose();
        }
    }

    public static void testDependencyInjection() {
        CustomFileReader reader = new CustomFileReader(() ->
            new File("D:\\Code\\Java\\code-design\\src\\com\\example\\Test.java")
        );
        System.out.println(reader.getFileName());
        System.out.println(reader.getFilePath());
    }

    public static void testBuilder() {
        ServiceProvider provider = new ServiceProvider.Builder("127.0.0.1", 80)
                .serviceName("userService")
                .maxConnection(100)
                .build();
        System.out.println(provider);

        Circle circle = new Circle.Builder(true, 5).build();
        System.out.println(circle);
    }

    public static void testSingleton() {
        Cat cat = Cat.getInstance();
        serializeAndDeserialize(cat);

        Dog dog = Dog.INSTANCE;
        serializeAndDeserialize(dog);
    }

    private static void serializeAndDeserialize(Object obj1) {
        byte[] bs = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (ObjectOutputStream out = new ObjectOutputStream(baos)) {
            out.writeObject(obj1);
            bs = baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (bs != null) {
            ByteArrayInputStream bais = new ByteArrayInputStream(bs);
            try (ObjectInputStream in = new ObjectInputStream(bais)) {
                Object obj2 = in.readObject();
                System.out.println(obj1.hashCode() + " " + obj2.hashCode());
                System.out.println(obj1 == obj2);
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}
